home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Applications / Nuntius 1.2 / src / Nuntius / UArticle.cp < prev    next >
Encoding:
Text File  |  1994-04-12  |  5.3 KB  |  263 lines  |  [TEXT/MPS ]

  1. // Copyright © 1992 Peter Speck, speck@dat.ruc.dk. All rights reserved.
  2. // UArticle.cp
  3.  
  4. #include "UArticle.h"
  5. #include "UArticleTextCache.h"
  6. #include "NetAsciiTools.h"
  7. #include "UOffsetLengthList.h"
  8. #include "ISO2022Conversion.h"
  9.  
  10. #include <Script.h>
  11.  
  12. #pragma segment MyArticle
  13.  
  14. #define qDebugArticleRefCount qDebug
  15.  
  16. // The parsing in this code assumes that the article text
  17. // is terminated with a null.
  18. // The text is obtained from PArticleTextCache.
  19.         
  20. pascal void TArticle::Initialize()
  21. {
  22.     inherited::Initialize();
  23.     fTextIndex = nil;
  24.     fGroupDotName = "";
  25.     fArticleID = -1;
  26.     fContainsJapaneseEncoding = false;
  27. }
  28.  
  29. void TArticle::IArticle(const CStr255 &groupDotName, long articleID)
  30. {
  31.     inherited::IObject();
  32.     FailInfo fi;
  33.     if (fi.Try())
  34.     {
  35.         TOffsetLengthList *olL = new TOffsetLengthList();
  36.         olL->IOffsetLengthList();
  37.         fTextIndex = olL;
  38.         fTextIndex->fAllocationIncrement = 50; 
  39.         // I think the default (6) is too low for this
  40.         
  41.         fGroupDotName = groupDotName;
  42.         fArticleID = articleID;
  43.         MakeTextIndex();
  44.         fi.Success();
  45.     }
  46.     else // fail
  47.     {
  48.         Free();
  49.         fi.ReSignal();
  50.     }
  51. }
  52.  
  53. pascal void TArticle::Free()
  54. {
  55.     FreeIfObject(fTextIndex); fTextIndex = nil;
  56.     inherited::Free();
  57. }
  58.  
  59.         
  60. void TArticle::GetLineInfo(ArrayIndex &noLines, ArrayIndex &bodyStartLineNo)
  61. {
  62. #if qDebug
  63.     if (fArticleID < 0)
  64.         ProgramBreak("TArticle::GetLineInfo called when fArticleID < 0");
  65. #endif
  66.     noLines = fTextIndex->GetSize();
  67.     bodyStartLineNo = fNoHeaderLines + 2;
  68. }
  69.  
  70. void TArticle::GetLine(ArrayIndex lineNo, CStr255 &text)
  71. {
  72. #if qDebug
  73.     if (lineNo < 1 || lineNo > fTextIndex->GetSize())
  74.         ProgramBreak("lineNo out of range");
  75. #endif
  76.     OffsetLength ol;
  77.     fTextIndex->AtGet(lineNo, ol);
  78.     HandleOffsetLength hol;
  79.     hol.fOffset = ol.fOffset;
  80.     hol.fLength = ol.fLength;
  81.     CStr255 dotName(fGroupDotName);
  82.     hol.fH = gArticleTextCache->GetArticleText(dotName, fArticleID);
  83.     if (!hol.fH)
  84.         text = "";
  85.     else
  86.         CopyHolToCStr255(hol, text);
  87.     if (fContainsJapaneseEncoding)
  88.     {
  89.         PStringTextCodeConverter cnv(text);
  90.         cnv.ConvertNet2Mac();
  91.         text = cnv.fOutputString;
  92.     }
  93. }
  94.             
  95. Boolean TArticle::GetHeader(const char *name, CStr255 &text)
  96. {
  97.     text.Length() = 0;
  98.     CStr255 dotName(fGroupDotName);
  99.     Handle h = gArticleTextCache->GetArticleText(dotName, fArticleID);
  100.     if (!h)
  101.         return false;
  102.     unsigned char *p = (unsigned char*)*h;
  103.     while (*p)
  104.     {
  105.         if (*p == 13)
  106.             return false; // start of body
  107.         if (*p <= 32)
  108.         {
  109.              // header was breaked, skip next line
  110.         }
  111.         else if (CompareStoreHeaderName(name, p, text))
  112.             return true;
  113.         while (*p != 13)
  114.             ++p;
  115.         ++p; // skip CR
  116.         if (*p == 10)
  117.             ++p; // skip LF
  118.     }
  119.     return false;
  120. }
  121.  
  122. Boolean TArticle::CompareStoreHeaderName(const char *name, unsigned char *lineStart, CStr255 &text)
  123. {
  124.     const unsigned char *theName = (const unsigned char*)name;
  125.     const unsigned char *p = lineStart;
  126.     while (*theName)
  127.     {
  128.         if (gToLowerChar[*p] != gToLowerChar[*theName])
  129.             return false;
  130.         ++p;
  131.         ++theName;
  132.     }
  133.     if (*p != ':')
  134.         return false;
  135.     ++p;
  136. // found it!
  137.     while (*p == 32) // skip leading spaces
  138.         ++p;
  139.     while (*p)
  140.     {
  141.         while (*p != 13)
  142.         {
  143.             text += *p++;
  144.         }
  145.         ++p; // skip CR
  146.         if (*p == 10)
  147.             ++p; // skip LF
  148.         if (*p == 13)
  149.             break; // start of body
  150.         if (*p > 32) // start of next header
  151.             break;
  152.         text += char(32); // soft break is space
  153.         while (*p == 9 || *p == 32) 
  154.             ++p;// skip all soft break spaces as they only count for one space
  155.     }
  156.     while (text.Length() && text[text.Length()] == 32) // strip spaces at end
  157.         --text.Length();
  158.     return true;
  159. }
  160.  
  161. Boolean TArticle::ContainsJapaneseEncoding()
  162. {
  163.     return fContainsJapaneseEncoding;
  164. }
  165.  
  166. Boolean TArticle::IsArticle(const CStr255 &groupDotName, long articleID)
  167. {
  168.     return groupDotName == fGroupDotName && articleID == fArticleID;
  169. }
  170.  
  171. void TArticle::GetArticleID(CStr255 &groupDotName, long &articleID)
  172. {
  173.     groupDotName = fGroupDotName;
  174.     articleID = fArticleID;
  175. }
  176.  
  177. void TArticle::MakeTextIndex()
  178. {
  179.     fTextIndex->DeleteAll();
  180.     fNoHeaderLines = 0;
  181.     fContainsJapaneseEncoding = false;
  182.     CStr255 dotName(fGroupDotName);
  183.     Handle h = gArticleTextCache->GetArticleText(dotName, fArticleID);
  184.     if (!h)
  185.         return;
  186.     register unsigned char *p = (unsigned char*)*h;
  187.     short noLines = 0;
  188.     Boolean inHeader = true;
  189.     long numEscapes = 0;
  190.     while (*p) 
  191.     {
  192.         unsigned char *lineStartP = p;
  193.         while (true)
  194.         {
  195.             switch (*p)
  196.             {
  197.                 case 0x1B:
  198.                     ++p;
  199.                   if      (*p == 0x28 && (p[1] == 0x42 || p[1] == 0x49 || p[1] == 0x4a))
  200.                         ; // ok
  201.                     else if (*p == 0x24 && (p[1] == 0x40 || p[1] == 0x42))
  202.                         ; // ok
  203.                     else
  204.                         continue; // bad
  205.                     ++numEscapes;
  206.                     p += 2;
  207.                     continue;
  208.  
  209.                 default:
  210.                     ++p;
  211.                     continue;
  212.  
  213.                 case 0:
  214.                 case 13:
  215.                     break;
  216.             }
  217.             break;
  218.         }
  219.         OffsetLength ol;
  220.         ol.fOffset = Ptr(lineStartP) - *h;
  221.         ol.fLength = p - lineStartP;
  222.         if (ol.fLength <= 90)
  223.             p++; // skip past CR
  224.         else // break line
  225.         {
  226.             long len = 80;
  227.             p = lineStartP + len - 1;
  228.             const long minLen = 20;
  229.             while (len > minLen && *p > 32)
  230.             {
  231.                 --len;
  232.                 --p;
  233.             }
  234.             if (len > minLen)
  235.             {
  236.                 ol.fLength = len;
  237.                 ++p;
  238.             }
  239.             else
  240.             {
  241.                 ol.fLength = 80;
  242.                 p = lineStartP + ol.fLength;
  243.             }
  244.         }
  245.         if (!ol.fLength)
  246.             inHeader = false;
  247.         if (*p == 10) 
  248.             ++p;
  249.         ++noLines;
  250.         if (inHeader)
  251.             ++fNoHeaderLines;
  252.  
  253.         // save pos
  254.         long offset = Ptr(p) - *h; // save pos
  255.         fTextIndex->InsertLast(ol);
  256.  
  257.         // restore pos
  258.         p = (unsigned char*)(*h + offset);
  259.     }
  260.     if (GetEnvirons(smEnabled) > 1)
  261.         fContainsJapaneseEncoding = (numEscapes >= 2);
  262. }
  263.